package com.huitu.whht.api.core.common.mybatis;

import com.huitu.whht.api.core.common.util.LocalDateTimeUtil;
import com.huitu.whht.api.core.common.util.LocalDateTimeUtil;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.property.PropertyTokenizer;
import org.apache.ibatis.reflection.wrapper.MapWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.sql.Clob;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.Map;

/**
 * 说明:
 * 1. resultType=Map时,对key进行驼峰转换(配置项useCamelCaseMapping需要为true)
 * 2. Map中的Clob字段转换为字符串,以防转json时出错
 *
 * @author ZhangAY
 * @date 2018-04-27
 */
public class MyMapWrapper extends MapWrapper {
    private static final Logger LOGGER = LoggerFactory.getLogger(MyMapWrapper.class);
    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    MyMapWrapper(MetaObject metaObject, Map<String, Object> map) {
        super(metaObject, map);
    }

    @Override
    public String findProperty(String name, boolean useCamelCaseMapping) {
        return (useCamelCaseMapping && ((name.charAt(0) >= 'A' && name.charAt(0) <= 'Z') || name.contains("_"))) ? toCamel(name) : name;
    }

    @Override
    public void set(PropertyTokenizer prop, Object value) {
        if (value instanceof Clob) {
            value = clobToString((Clob) value);
        } else if (value instanceof Date) {
            value = sdf.format(value);
        } else if (value instanceof LocalDate) {
            value = LocalDateTimeUtil.DATE_TIME_FORMATTER_YMD_HMS.format((LocalDate) value);
        } else if (value instanceof LocalDateTime) {
            value = LocalDateTimeUtil.DATE_TIME_FORMATTER_YMD_HMS.format((LocalDateTime) value);
        }
        super.set(prop, value);
    }

    /**
     * 将下划线风格替换为驼峰风格
     *
     * @param str 要替换的字符串
     * @return 驼峰转换结果
     */
    private String toCamel(String str) {
        StringBuilder sb = new StringBuilder();
        boolean nextUpperCase = false;
        char c;
        for (int i = 0; i < str.length(); i++) {
            c = str.charAt(i);
            if (c == '_') {
                if (sb.length() > 0) {
                    nextUpperCase = true;
                }
            } else {
                if (nextUpperCase) {
                    sb.append(Character.toUpperCase(c));
                    nextUpperCase = false;
                } else {
                    sb.append(Character.toLowerCase(c));
                }
            }
        }
        return sb.toString();
    }

    /**
     * oracle.sql.Clob类型转换成String类型
     */
    private String clobToString(Clob clob) {
        StringBuffer content = new StringBuffer(32);
        String str;
        try (BufferedReader bufferedReader = new BufferedReader(clob.getCharacterStream())) {
            while ((str = bufferedReader.readLine()) != null) {
                content.append(str);
            }
        } catch (Exception e) {
            LOGGER.error(" MyMapWrapper Clob to String 转换失败");
            LOGGER.error(e.toString());
        }
        return content.toString();
    }
}
